package org.liaohailong.library.image.victor;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.URL;

import pl.droidsonroids.gif.GifDrawable;

/**
 * Author: liaohailong
 * Date: 2019/7/14
 * Time: 11:06
 * Description: 任务执行
 **/
public class AvatarWorker implements Runnable {
    private final AvatarManager manager;
    private final String url;
    private final WeakReference<ImageView> imageView;
    private final int width;
    private final int height;
    private final WeakReference<Drawable> error;
    private Avatar.OnImageCallback callback;

    AvatarWorker(@NonNull AvatarManager manager, @NonNull String url, @Nullable ImageView imageView,
                 int width, int height, @Nullable Drawable error, @Nullable Avatar.OnImageCallback callback) {
        this.manager = manager;
        this.url = url;
        this.imageView = new WeakReference<>(imageView);
        this.width = width;
        this.height = height;
        this.error = new WeakReference<>(error);
        this.callback = callback;
    }

    public String getUrl() {
        return url;
    }

    @Override
    public void run() {
        AvatarCache avatarCache = Avatar.INSTANCE.getAvatarCache();
        boolean isCached = avatarCache.isCached(url);

        if (isCached) {
            // 先从运行内存中获取
            Bitmap bitmap = avatarCache.getBitmap(url);
            if (bitmap != null) {
                Resources resources = Avatar.INSTANCE.getContext().getResources();
                BitmapDrawable bitmapDrawable = new BitmapDrawable(resources, bitmap);
                done(true, bitmapDrawable);
            } else {
                // 从硬盘缓存中获取
                String filePath = avatarCache.getFilePath(url);
                loadSourceFromCache(filePath);
            }
        } else {
            loadSourceFromHttp();
        }
    }

    private void loadSourceFromCache(String path) {
        // 判断是否gif图，两种处理方式
        try {
            if (isGifFile(new File(path))) {
                GifDrawable gifDrawable = new GifDrawable(path);
                done(true, gifDrawable);
            } else {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;
                BitmapFactory.decodeFile(path, options);

                int wSize = (int) Math.ceil(options.outWidth * 1f / width);
                int hSize = (int) Math.ceil(options.outHeight * 1f / height);
                options.inSampleSize = Math.max(wSize, hSize);
                options.inMutable = true;
                options.inJustDecodeBounds = false;
                Bitmap bitmap = BitmapFactory.decodeFile(path, options);
                // 内存缓存Bitmap
                Avatar.INSTANCE.getAvatarCache().saveBitmap(url, bitmap);
                Resources resources = Avatar.INSTANCE.getContext().getResources();
                BitmapDrawable bitmapDrawable = new BitmapDrawable(resources, bitmap);
                done(true, bitmapDrawable);
            }
        } catch (Exception e) {
            done(false, null);
        }
    }

    private void loadSourceFromHttp() {
        // 本地缓存路径
        String filePath = Avatar.INSTANCE.getAvatarCache().getFilePath(url);

        // 开始网络请求
        InputStream is = null;
        BufferedOutputStream bos = null;
        try {
            HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.setDoOutput(false);
            urlConnection.connect();
            int responseCode = urlConnection.getResponseCode();

            boolean is200 = responseCode == HttpURLConnection.HTTP_OK;
            boolean is206 = responseCode == HttpURLConnection.HTTP_PARTIAL;
            if (is200 || is206) {
                // 保存本地
                is = urlConnection.getInputStream();
                bos = new BufferedOutputStream(new FileOutputStream(new File(filePath)));
                byte[] buffer = new byte[1024];
                int length;
                while ((length = is.read(buffer)) != -1) {
                    bos.write(buffer, 0, length);
                }
                bos.flush();

                closeIO(is);
                closeIO(bos);
                urlConnection.disconnect();

                // 加载本地图片
                loadSourceFromCache(filePath);
            } else {
                done(false, null);
            }
        } catch (Exception e) {
            e.printStackTrace();

            done(false, null);
        } finally {
            closeIO(is);
            closeIO(bos);
        }
    }


    private void done(final boolean success, final @Nullable Drawable source) {
        // 主线程回调结果
        manager.postMainThread(new Runnable() {
            @Override
            public void run() {
                // 移除并检查请求任务
                manager.removeAndCheckSubmitQueen(success, AvatarWorker.this);

                ImageView imageView = AvatarWorker.this.imageView.get();
                if (imageView != null) {
                    if (success) {
                        imageView.setImageDrawable(source);
                    } else {
                        imageView.setImageDrawable(error.get());
                    }
                }

                if (callback != null) {
                    if (imageView != null) {
                        callback.onDisplayImageComplete(success, source);
                    } else {
                        // 本地缓存路径
                        String filePath = Avatar.INSTANCE.getAvatarCache().getFilePath(url);
                        callback.onDownloadImageComplete(success, filePath);
                    }
                }
            }
        });
    }


    private void closeIO(Closeable closeable) {
        try {
            if (closeable != null) {
                closeable.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private boolean isGifFile(File file) {
        try {
            FileInputStream inputStream = new FileInputStream(file);
            int[] flags = new int[5];
            flags[0] = inputStream.read();
            flags[1] = inputStream.read();
            flags[2] = inputStream.read();
            flags[3] = inputStream.read();
            inputStream.skip(inputStream.available() - 1);
            flags[4] = inputStream.read();
            inputStream.close();
            return flags[0] == 71 && flags[1] == 73 && flags[2] == 70 && flags[3] == 56 && flags[4] == 0x3B;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}
